/*
 * Noxim - the NoC Simulator
 *
 * (C) 2005-2010 by the University of Catania
 * For the complete list of authors refer to file ../doc/AUTHORS.txt
 * For the license applied to these sources refer to file ../doc/LICENSE.txt
 *
 * This file contains the declaration of the tile
 */

#ifndef __NOXIMTILE_H__
#define __NOXIMTILE_H__

#include <systemc.h>
#include "NoximRouter.h"
#include "NoximProcessingElement.h"
using namespace std;

SC_MODULE(NoximTile)
{

    // I/O Ports
    sc_in_clk clock;		                // The input clock for the tile
    sc_in <bool> reset;	                        // The reset signal for the tile

    signal <NoximFlit> flit_rx[DIRECTIONS];	// The input channels
    signal <bool> req_rx[DIRECTIONS];	        // The requests associated with the input channels
    signal <bool> ack_rx[DIRECTIONS];	        // The outgoing ack signals associated with the input channels
    
    signal <NoximFlit> flit_tx[DIRECTIONS];	// The output channels
    signal <bool> req_tx[DIRECTIONS];	        // The requests associated with the output channels
    signal <bool> ack_tx[DIRECTIONS];	        // The outgoing ack signals associated with the output channels

    signal <int> free_slots[DIRECTIONS];
    signal <int> free_slots_neighbor[DIRECTIONS];

    // NoP related I/O
    signal < NoximNoP_data > NoP_data_out[DIRECTIONS];
    signal < NoximNoP_data > NoP_data_in[DIRECTIONS];

    // Signals
    signal <NoximFlit> flit_rx_local;	// The input channels
    signal <bool> req_rx_local;              // The requests associated with the input channels
    signal <bool> ack_rx_local;	        // The outgoing ack signals associated with the input channels

    signal <NoximFlit> flit_tx_local;	// The output channels
    signal <bool> req_tx_local;	        // The requests associated with the output channels
    signal <bool> ack_tx_local;	        // The outgoing ack signals associated with the output channels

    signal <int> free_slots_local;
    signal <int> free_slots_neighbor_local;

    // Instances
    NoximRouter *r;		                // Router instance
    NoximProcessingElement *pe;	                // Processing Element instance

//+CHDR tile-router and router-pe connection -----------------------------------
        
    void copy_signal_from_tile(){
	for (int i = 0; i < DIRECTIONS; i++) {
	    r->flit_rx[i] = flit_rx[i].read();
	    r->req_rx[i]  = req_rx[i].read();
        
	    r->ack_tx[i] = ack_tx[i].read();
	    r->free_slots_neighbor[i] = free_slots_neighbor[i].read();
	    r->NoP_data_in[i]  = NoP_data_in[i].read();
	}
    }
    void copy_signal_to_tile(){
	for (int i = 0; i < DIRECTIONS; i++) {
	    ack_rx[i] = r->ack_rx[i].read();

	    flit_tx[i] = r->flit_tx[i].read();
	    req_tx[i]  = r->req_tx[i].read();

	    free_slots[i] = r->free_slots[i].read();

	    // NoP 
	    NoP_data_out[i] = r->NoP_data_out[i].read();
	}

	r->flit_rx[DIRECTION_LOCAL]= pe->flit_tx;
	r->req_rx[DIRECTION_LOCAL] = pe->req_tx;
	pe->ack_tx = r->ack_rx[DIRECTION_LOCAL];

	r->free_slots[DIRECTION_LOCAL] =(free_slots_local);

	pe->flit_rx= r->flit_tx[DIRECTION_LOCAL];
	pe->req_rx = r->req_tx[DIRECTION_LOCAL];
	r->ack_tx[DIRECTION_LOCAL] = pe->ack_rx;

	pe->free_slots_neighbor = r->free_slots_neighbor[DIRECTION_LOCAL];
    }
    void run_one_cycle(){
        copy_signal_from_tile();
        pe->Process();
        r ->Process();
        copy_signal_to_tile();
    }
        
//-CHDR tile-router and router-pe connection -----------------------------------
    // Constructor

    SC_CTOR(NoximTile) {

	// Router pin assignments
	r = new NoximRouter("Router");
	r->clock(clock);
	r->reset(reset);
	// Processing Element pin assignments
	pe = new NoximProcessingElement("ProcessingElement");
	pe->clock(clock);
	pe->reset(reset);
	

    }

};

#endif
